package com.scs.application.core.utils;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.ReflectionUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * ${DESCRIPTION}
 */

public class SpringUtils implements ApplicationContextAware {

    // 上下文对象实例
    private static ApplicationContext applicationContext;
    private static Validator validator =  Validation.buildDefaultValidatorFactory().getValidator();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        return (T) applicationContext.getBean(name);
    }
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
    /**
     * @param clazz 类
     * @param methodName
     *            方法名称
     * @param params
     *            参数
     * @return 返回值
     * @throws Exception
     */
    public static Object invokeMethod(Class clazz, String methodName, Object... params) throws Exception {
        Object service = getBean(clazz);
        Class<? extends Object>[] paramClass = null;
        if (params != null) {
            int paramsLength = params.length;
            paramClass = new Class[paramsLength];
            for (int i = 0; i < paramsLength; i++) {
                paramClass[i] = params[i].getClass();
            }
        }
        // 找到方法
        Method method = ReflectionUtils.findMethod(service.getClass(), methodName, paramClass);
        // 执行方法
        return ReflectionUtils.invokeMethod(method, service, params);
    }

    /** 查找类时忽略参数
     * @param clazz 类
     * @param methodName
     *            方法名称
     * @param params
     *            参数
     * @return 返回值
     * @throws Exception
     */
    public static Object invokeMethodIgnoreParams(Class clazz, String methodName, Object... params) throws Exception {
        Object service = getBean(clazz);
        // 找到方法
        Method method = ReflectionUtils.findMethod(service.getClass(), methodName, null);

        Class<?>[] parameterTypes = method.getParameterTypes();
        if (parameterTypes.length == 0) {
            params = null;
        }
        //参数转换定长
        if (params != null) {
            int paramsLength = parameterTypes.length;
            Object[] paramsFixed = new Object[paramsLength];
            for (int i = 0; i < paramsLength; i++) {
                for(Object param : params) {
                    if(parameterTypes[i].getName().equals(param.getClass().getName())) {
                        paramsFixed[i] = param;
                    }
                }
            }
            return ReflectionUtils.invokeMethod(method, service, paramsFixed);
        }
        return ReflectionUtils.invokeMethod(method, service, null);

    }

    /**
     * @param clazzName 类名称
     * @param methodName
     *            方法名称
     * @param params
     *            参数
     * @return 返回值
     * @throws Exception
     */
    public static Object invokeMethod(String clazzName, String methodName, Object... params) throws Exception {
        Object service = getBean(clazzName);
        Class<? extends Object>[] paramClass = null;
        if (params != null) {
            int paramsLength = params.length;
            paramClass = new Class[paramsLength];
            for (int i = 0; i < paramsLength; i++) {
                paramClass[i] = params[i].getClass();
            }
        }
        // 找到方法
        Method method = ReflectionUtils.findMethod(service.getClass(), methodName, paramClass);
        // 执行方法
        return ReflectionUtils.invokeMethod(method, service, params);
    }

    /**
    * @Description： 手动校验实体属性
     * @return  返回null，则校验成功，否则返回 sp_code供应商代码不能为空
    */
    public static  String validateEntity(Object obj){
        Set<ConstraintViolation<Object>> set = validator.validate(obj, Default.class);
        if( CollectionUtils.isNotEmpty(set) ){
            Map<String,String> errorMsg = new HashMap<String,String>();
            for(ConstraintViolation<Object> cv : set){
                return cv.getPropertyPath().toString() + cv.getMessage();
            }
        }
        return null;
    }

}
